package arch.service.impl.user;

import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import arch.dao.user.PrivilegeDao;
import arch.domain.user.Button;
import arch.domain.user.Module;
import arch.domain.user.Privilege;
import arch.domain.user.Role;
import arch.domain.user.User;
import arch.domain.user.Privilege.Type;
import arch.service.user.ButtonService;
import arch.service.user.ModuleService;
import arch.service.user.PrivilegeService;
import arch.service.user.RoleService;
import arch.util.UUID;
/**
 * 
 * @author ZhaoWangLong Sep 7, 2012
 *
 */
@Service("privilegeService")
@Transactional
public class PrivilegeServiceBean implements PrivilegeService {
	@Resource private PrivilegeDao privilegeDao;
	@Resource private RoleService roleService;
	@Resource private ModuleService moduleService;
	@Resource private ButtonService buttonService;
	private final Logger logger = Logger.getLogger(PrivilegeServiceBean.class);
	
	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	public Privilege find(Privilege privilege, boolean role) {
		Privilege p = find(privilege);
		if(p!=null && role)
			p.setRoles(this.roleService.findListByPrivilege(privilege));
		return p;
	}

	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	public List<Privilege> findList(Role role, Type type) {
		StringBuffer sql = new StringBuffer();
		sql.append("select ID, TYPE, RESOURCE_ID, IS_ABSTRACT, SCOPE, DESCRIPTION, ")
			.append(" CREATE_TIME, LAST_UPDATE_TIME from ID_PRIVILEGE  ");
		
		StringBuffer condition = new StringBuffer();
		if(role!=null || type!=null)
			condition.append(" where ");
		
		if(role!=null)
			condition.append(" ID in (select PRIVILEGE_ID from ID_ROLE_PRIVILEGE where ROLE_ID = '")
				.append(role.getRoleId())
				.append("' ) and ");
		if(type!=null)
			condition.append(" TYPE = '").append(type.name()).append("' and ");
		
		String temp = condition.substring(0,condition.lastIndexOf("and"));
		sql.append(temp);
		
		logger.debug("SQL > "+sql.toString());
		return setValues(this.privilegeDao.queryList(sql.toString()));
	}

	public void add(Privilege entity) {
		String privilegeId = UUID.id("ID", "PE");
		Timestamp createTime = new Timestamp(new Date().getTime());
		
		entity.setId(privilegeId);
		entity.setCreateTime(createTime);
		entity.setLastUpdateTime(createTime);

		this.privilegeDao.persist(entity);
	}

	public void delete(Privilege primaryKey) {
		if(primaryKey.getId()!=null&&!"".equals(primaryKey.getId()))
			this.privilegeDao.remove(primaryKey.getId());
		else{
			String type = primaryKey.getType()==null?null:primaryKey.getType().name();
			String resourceId = primaryKey.getResourceId();
			String sql1 = "delete from ID_ROLE_PRIVILEGE where PRIVILEGE_ID in "
				+"(select ID from ID_PRIVILEGE where (TYPE,RESOURCE_ID) = (?,?) )";
			String sql2 = "delete from ID_PRIVILEGE where (TYPE,RESOURCE_ID) = (?,?)";
			
			this.privilegeDao.update(sql1, type,resourceId);
			this.privilegeDao.update(sql2, type,resourceId);
		}
			
	}
	
	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	public Privilege find(Privilege primaryKey) {
		return this.privilegeDao.find(primaryKey.getId());
	}

	public void update(Privilege entity) {
		Timestamp lastUpdateTime = new Timestamp(new Date().getTime());

		entity.setLastUpdateTime(lastUpdateTime);
		this.privilegeDao.merge(entity);
	}

	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	public List<Privilege> findList(Type type) {
		StringBuffer sql = new StringBuffer();
		sql.append("select ID, TYPE, RESOURCE_ID, IS_ABSTRACT, SCOPE, DESCRIPTION, ")
			.append(" CREATE_TIME, LAST_UPDATE_TIME from ID_PRIVILEGE where TYPE = ? ");
		
		logger.debug("SQL > "+sql.toString());
		return setValues(this.privilegeDao.queryList(sql.toString(),type.name()));
	}

	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	private List<Privilege> setValues(List<Privilege> privileges){
		if(privileges!=null && privileges.size()>0){
			Map<String,Object> caches = cachePrivileges();
			for (Privilege privilege : privileges) {
				if(privilege.getType()!=null&& caches!=null && caches.size()>0){
					if("MODULE".equals(privilege.getType().name()))
						privilege.setModule(caches.get(privilege.getResourceId())==null?null:(Module)caches.get(privilege.getResourceId()));
					if("BUTTON".equals(privilege.getType().name()))
						privilege.setButton(caches.get(privilege.getResourceId())==null?null:(Button)caches.get(privilege.getResourceId()));
				}
			}
		}
		return privileges;
	}
	
	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	private Map<String,Object> cachePrivileges(){
		Map<String,Object> map = new HashMap<String, Object>();
		List<Module> modules = this.moduleService.findAll();
		if(modules!=null && modules.size() >0){
			for(Module m : modules)
				map.put(m.getModuleId(), m);
		}
		List<Button> buttons = this.buttonService.findList(new Button());
		if(buttons!=null && buttons.size()>0){
			for(Button b : buttons)
				map.put(b.getButtonId(), b);
		}
		return map;
	}
	
	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	public List<Privilege> findList(User user, Type type) {
		StringBuffer sql = new StringBuffer();
		sql.append("select ID, TYPE, RESOURCE_ID, IS_ABSTRACT, SCOPE, DESCRIPTION, ")
			.append(" CREATE_TIME, LAST_UPDATE_TIME from ID_PRIVILEGE where ID in ( ")
			.append(" select PRIVILEGE_ID from ID_ROLE_PRIVILEGE where ROLE_ID in (")
			.append(" select ROLE_ID from ID_ROLE_USER where USER_ID = ? ))");
		
		if(type!=null)
			sql.append(" and TYPE = '").append(type.name()).append("' ");
		
		logger.debug("SQL > "+sql.toString());
		if(user!=null)
			return setValues(this.privilegeDao.queryList(sql.toString(),user.getUserId()));
		else
			return null;
	}
}
